<!doctype html>
<html>

<head>
	<meta charset="UTF-8">
	<title>抛物线效果 | By xiaohigh</title>
	<style type="text/css">
		* {
			padding: 0px;
			margin: 0px;
		}

		body {
			height: 100vh;
		}

		#move {
			width: 40px;
			height: 40px;
			position: absolute;
			left: 325px;
			background: black;
			top: 200px;
			border-radius: 50%;
		}

		#middle {
			width: 40px;
			height: 40px;
			position: absolute;
			left: 1050px;
			background: black;
			top: 50px;
			border-radius: 50%;
		}

		#right {
			width: 40px;
			height: 40px;
			position: absolute;
			left: 1600px;
			background: black;
			top: 250px;
			border-radius: 50%;
		}

		body {
			background: radial-gradient(#eee, #666);
		}
	</style>
</head>

<body>
	<div id="move"></div>
	<div id="middle"></div>
	<div id="right"></div>
	<script type="text/javascript">
		//封装函数 通过三个点的坐标获取二元一次方程系数 
		function getSolve(arr1, arr2, arr3) {
			var d = arr1[0];
			var e = arr1[1];
			var f = arr2[0];
			var g = arr2[1];
			var h = arr3[0];
			var i = arr3[1];

			var a = ((g - i) * (f - d) / (f - h) - (g - e)) / ((f * f - h * h) * (f - d) / (f - h) - (f * f - d * d));
			var b = (((g - i) * (f * f - d * d)) / (f * f - h * h) - (g - e)) / ((f - h) * (f * f - d * d) / (f * f - h * h) -
				(f - d));
			var c = ((g * h - f * i) * (d * d * f - f * f * d) / (f * f * h - h * h * f) - (f * e - d * g)) / ((h - f) * (d *
				d * f - f * f * d) / (f * f * h - h * h * f) - (f - d));
			var d = [a, b, c];

			return d;
		}

		//抛弧线轨迹移动
		function pao() {
			//设置小球移动的步进
			var step = 10;
			var arr1 = [move.offsetLeft, -move.offsetTop];
			var arr2 = [middle.offsetLeft, -middle.offsetTop];
			var arr3 = [right.offsetLeft, -right.offsetTop];
			//move元素当前的left的值
			var currentLeft = move.offsetLeft;
			//获取二元一次方程的系数
			var EYC = getSolve(arr1, arr2, arr3);
			//开始定时器前  首先停止原来的定时器
			clearInterval(inte);
			inte = setInterval(function () {
				//x轴位置
				var newLeft = move.offsetLeft + step;
				move.style.left = newLeft + 'px';
				//计算y轴的位置
				var newTop = EYC[0] * newLeft * newLeft + EYC[1] * newLeft + EYC[2];
				move.style.top = -newTop + 'px';
				//检测是否到达边界
				if (newLeft >= document.documentElement.clientWidth - 50 || newLeft <= currentLeft) {
					//反向运动
					step *= -1
				}
			}, 10)
		}

		//设置可移动的元素对象
		function moveElement(id) {
			var el = document.getElementById(id); //获取元素的对象
			var isDown = false; //设置一个局部变量
			var x = 0;
			var y = 0;
			var l = 0;
			var t = 0;
			//绑定鼠标按下事件
			el.onmousedown = function (e) {
				// alert($(this).attr('id'));
				//获取元素上一个状态的位置和长宽
				x = e.clientX;
				y = e.clientY;
				l = this.offsetLeft;
				t = this.offsetTop;
				isDown = true;
				//鼠标移动的事件
				window.onmousemove = function (e) {
					if (!isDown) return false;
					//当前状态的鼠标位置
					var cx = e.clientX;
					var cy = e.clientY;
					//计算新的位置
					var newL = (cx - x) + l;
					var newT = (cy - y) + t;
					el.style.left = newL + 'px';
					el.style.top = newT + 'px';
				}
				//鼠标抬起的时候事件
				window.onmouseup = function () {
					isDown = false;
				}
			}
		}

		//移动的定时器
		var inte = null;
		//获取元素
		const move = document.querySelector('#move');
		const middle = document.querySelector('#middle');
		const right = document.querySelector('#right');

		//使三个小圆点可拖拽		
		new moveElement('move');
		new moveElement('middle');
		new moveElement('right');

		//绑定键盘按下事件
		window.onkeydown = function (e) {
			switch (e.keyCode) {
				case 32:
					pao();
					break;
				case 83: // s 按键
				case 13: // 回车
					clearInterval(inte);
			}
		}
	</script>
</body>

</html>